package com.black.cat.jvm;

import com.black.cat.jvm.classfile.ClassFile;
import com.black.cat.jvm.classfile.MemberInfo;
import com.black.cat.jvm.classpath.Classpath;
import com.black.cat.jvm.rtda.Frame;
import com.black.cat.jvm.rtda.LocalVars;
import com.black.cat.jvm.rtda.OperandStack;


/**
 * @Author blackcat
 * @create 2021/8/11 13:43
 * @version: 1.0
 * @description:命令行工具
 */
public class Main {

    public static void main(String[] args) {
        String[] argv = {"-classpath", "D:\\develop\\code\\jjvm\\jvm-05\\target\\classes", "com.black.cat.jvm.MainTest"};
        Cmd cmd = Cmd.parse(argv);
        if (!cmd.ok || cmd.helpFlag) {
            System.out.println("Usage: <main class> [-options] class [args...]");
            return;
        }
        if (cmd.versionFlag) {
            System.out.println("java version \"1.8.0\"");
            return;
        }
        startJVM(cmd);
    }

    private static void startJVM(Cmd cmd) {
        Classpath classpath = new Classpath(cmd.jre, cmd.classpath);
        System.out.printf("classpath:%s class:%s args:%s\n", classpath, cmd.getMainClass(), cmd.getAppArgs());
        String className = cmd.getMainClass().replace(".", "/");
        ClassFile classFile = loadClass(className, classpath);
        MemberInfo mainMethod = getMainMethod(classFile);
        if (null == mainMethod) {
            System.out.println("Main method not found in class " + cmd.classpath);
            return;
        }
        new Interpret(mainMethod);
    }


    private static ClassFile loadClass(String className, Classpath cp) {
        try {
            byte[] classData = cp.readClass(className);
            return new ClassFile(classData);
        } catch (Exception e) {
            System.out.println("Could not find or load main class " + className);
            e.printStackTrace();
        }
        return null;
    }

    //找到主函数入口方法
    private static MemberInfo getMainMethod(ClassFile cf) {
        if (null == cf) return null;
        MemberInfo[] methods = cf.getMethodInfos();
        for (MemberInfo m : methods) {
            if ("main".equals(m.name()) && "([Ljava/lang/String;)V".equals(m.descriptor())) {
                return m;
            }
        }
        return null;
    }
}
